﻿using System.IO.Ports;
using System.Windows;
using Oxage.Common;
using Oxage.Windows.Controls;
using Arguments = Oxage.Windows.Controls.Arguments;

namespace Oxage.Commands
{
	[CommandLineHandler("uart", "Handle serial port communication")]
	public class UartCommandLineHander : ICommandLineHandler
	{
		#region Private members
		private static bool listen = false;
		private static SerialPort port;
		#endregion

		#region ICommandLineHandler Members
		public void Run(IConsole console, string line, string command, Arguments args)
		{
			if (args.Count == 0 || args.Help)
			{
					console.WriteLine("Handle serial port communication");
					console.WriteLine();
					console.WriteLine("Usage:");
					console.WriteLine("  uart [command] <options>");
					console.WriteLine();
					console.WriteLine("Commands:");
					console.WriteLine("  help    Display this message");
					console.WriteLine("  open    Open serial port");
					console.WriteLine("  close   Close serial port");
					console.WriteLine("  send    Send data to device");
					console.WriteLine("  listen  Listen for incoming packets");
					console.WriteLine("  config  Get serial port configuration");
					console.WriteLine("  list    List devices");
					console.WriteLine();
					console.WriteLine("Examples:");
					console.WriteLine("  uart open COM1 9600 8N1");
					console.WriteLine("  uart send G01 X10 Y20 Z30");
					console.WriteLine("  uart config");
					return;
			}

			if (port == null)
			{
				port = new SerialPort();
				port.DataReceived += (sender, e) =>
				{
					if (listen)
					{
						Application.Current.Dispatcher.Invoke((CrossThreadDelegate)delegate
						{
							string data = port.ReadExisting();
							console.Write(data);
						});
					}
				};
			}

			switch (args[0])
			{
				case "open":
					port.PortName = args[1];
					port.BaudRate = int.Parse(args[2]);
					port.DataBits = 8;
					port.Parity = Parity.None;
					port.StopBits = StopBits.One;
					port.Handshake = Handshake.None;
					console.WriteLine("Opening serial port: " + port.PortName + " " + port.BaudRate);
					port.Open();
					console.WriteLine("Serial port opened");
					break;

				case "close":
					console.WriteLine("Serial port closed");
					port.Close();
					break;

				case "send":
					string raw = Arguments.BuildRawArguments(args.Range(1));
					console.WriteLine("Serial port: " + raw);
					port.Write(raw);
					break;

				case "listen":
					console.WriteLine("Serial port listening enabled");
					listen = true;
					break;

				case "config":
					//TODO: Move to SerialPortModel (or ViewModel) and implement methods for auto binding
					string config = string.Format("{0} {1} {2} {3} {4}", port.PortName, port.BaudRate, port.DataBits, port.Parity, port.StopBits);
					console.WriteLine(config);
					break;

				case "list":
					var portNames = SerialPort.GetPortNames();
					foreach (string portName in portNames)
					{
						console.WriteLine(portName);
					}
					break;

				default:
					console.WriteLine("Unknown argument: " + args[0]);
					break;
			}
		}
		#endregion
	}
}
